/*
===========================================================================
This source file is part of DyLab (Dynamic Laboratory)
For the latest info, see http://dylab-modules.googlecode.com

Copyright (c) 2006-2008 Lukas Krejci
(krejci.lukas@volny.cz)

This file is part of DyLab.

    DyLab is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    DyLab is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DyLab.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/

#ifndef __dylab_dotT4Obj_ModelStructureLoader_h__
#define __dylab_dotT4Obj_ModelStructureLoader_h__

//===========================================================================================
#include <dylab/utils/formats/WavefrontObjFormat.h>
#include <dylab/utils/geometry/AxisAlignedBox.h>
#include <dylab/utils/topology/TriComplex.h>
#include <dylab/simobject/ComModelStructureLoader.h>

//===========================================================================================
namespace dylab {

    /**  
     */
    class dotT4Obj_ModelStructureLoader 
        : public ComModelStructureLoader
        , private WavefrontObjFormat::IDataConsumer
    {
    private:
        // cull methods labels
        enum cullmethod_t {
            CM_TEST_APEXES,
            CM_TEST_BOUNDARYFACES,
            CM_TEST_BARYCENTER
        };
    public:
        static const String COMPONENT_NAME;        
    private:
        //-----------------------------------------------------------------------------
        // attributes of a vertex in the triangular mesh (surface mesh)
        struct MeshVertex
        {
            Vector3 position;
            Vector3 normal;
            real_t  u, v;
        };
    private:
        // for convenient (and less typing) only
        typedef TriComplex<MeshVertex>  TriComplexT;
        typedef TriComplexT::Simplex    Simplex;
        typedef TriComplexT::NodeSimplex NodeSimplex;
        typedef TriComplexT::EdgeSimplex EdgeSimplex;
        typedef TriComplexT::TriSimplex  Face;
    private:
        ///
        TriComplexT mBoundaryFaces;
        /// structure scale factor is used on boundary mesh before tetrahedra generation
        real_t mBoundaryMeshScale;
        /// structure translate vector is used on boundary mesh before tetrahedra generation
        Vector3 mBoundaryMeshTranslate;
        /// boundary mesh aabb
        AxisAlignedBox mBoundaryMeshBoundingBox;
        /// define the distance between nodes (in perpendicular directions)
        uint32_t mNodeStep;
        /// mass of one node
        real_t mNodeMass;
        ///
        bool mDebugMode;
    public:        
        dotT4Obj_ModelStructureLoader();        
        virtual void loadFromPropertyTree(const PropertyTree & _pt);;                

    private:        
        virtual void onCreateVertex(const Vector3 & _v);        
        virtual void onSetVertexNormal(uint32_t _index, const Vector3 & _n);        
        virtual void onSetVertexTexture(uint32_t _index, real_t _u, real_t _v = DYLAB_R(0), real_t _w = DYLAB_R(0));        
        virtual void onCreateFace(uint32_t _v1, uint32_t _v2, uint32_t _v3);        

        void _buildModel(const String & _boundaryMeshFile);        
        void _generateBox(const Vector3 & _start, uint32_t _width, uint32_t _height, uint32_t _depth);        
        void _cullOuterTetrahedra(cullmethod_t _cullMethod);        
        bool _isOutsideBoundary(const Vector3 & _p);        
        void _removeDegeneratedTetrahedra();        
        uint32_t _subdivideTetrahedraByBoundaryVertices();        
        uint32_t _subdivideTetrahedraByBoundaryFaces();          
        uint32_t _subdivideTetrahedraByBoundaryEdges();
    };
}
//===========================================================================================
#endif // __dylab_dotT4Obj_ModelStructureLoader_h__